﻿using AutoMapper;
using Microsoft.Extensions.DependencyInjection;
using Modules.Device.Entitys;
using Modules.Device.Repositories;
using Modules.FaceScan;
using Modules.Person;
using Modules.Project;
using Modules.Project.Entitys;
using Modules.Project.Models;
using Newtonsoft.Json;
using PmSoft;
using PmSoft.ApplicationContext;
using static Modules.Device.CheckInDeviceConstants;
using static Modules.Person.PersonConstants;

namespace Modules.Device;

[UseDI(ServiceLifetime.Scoped)]
public class CheckinDeviceCommandService
{
    private readonly CheckinDeviceCommandRepository projectCheckinDeviceCommandRepository;
    private readonly PersonService personService;
    private readonly ProjectGroupMemberService projectGroupMemberService;
    private readonly FacePhotoService personFaceService;
    private readonly IMapper mapper;
    private readonly IApplicationContext applicationContext;

    public CheckinDeviceCommandService(CheckinDeviceCommandRepository projectCheckinDeviceCommandRepository, PersonService personService, ProjectGroupMemberService projectGroupMemberService, FacePhotoService personFaceService, IMapper mapper, IApplicationContext applicationContext)
    {
        this.projectCheckinDeviceCommandRepository = projectCheckinDeviceCommandRepository;
        this.personService = personService;
        this.projectGroupMemberService = projectGroupMemberService;
        this.personFaceService = personFaceService;
        this.mapper = mapper;
        this.applicationContext = applicationContext;
    }

    public IPagedList<CheckinDeviceCommand> GetProjectCheckinDeviceCommands(CheckinDeviceCommandQuery query, int pageIndex, int pageSize)
    {
        return projectCheckinDeviceCommandRepository.GetProjectCheckinDeviceCommands(query, pageIndex, pageSize);
    }

    public void Create(CheckinDeviceCommand command)
    {
        command.MessageId = command.MessageId.Replace("-", "");
        projectCheckinDeviceCommandRepository.Insert(command);
    }

    public void Update(CheckinDeviceCommand command)
    {
        projectCheckinDeviceCommandRepository.Update(command);
    }

    public void Delete(int id)
    {
        projectCheckinDeviceCommandRepository.DeleteByEntityId(id);
    }

    public void Deleted(IEnumerable<int> ids)
    {
        foreach (var id in ids)
        {
            Delete(id);
        }
    }

    public CheckinDeviceCommand? GetProjectCheckinDeviceCommand(int id)
    {
        return projectCheckinDeviceCommandRepository.Get(id);
    }

    public CheckinDeviceCommand? GetProjectCheckinDeviceCommand(string messageId)
    {
        return projectCheckinDeviceCommandRepository.GetProjectCheckinDeviceCommand(messageId);
    }

    /// <summary>
    /// 向指定项目所有设备下发命令
    /// </summary>
    /// <param name="projectId"></param>
    /// <param name="command"></param>
    /// <returns></returns>
    public void Send(int projectId, CheckinDeviceCommand command)
    {
        var checkinDeviceService = applicationContext.GetService<CheckinDeviceService>();
        var memberService = applicationContext.GetService<ProjectGroupMemberService>();

        var members = memberService.GetProjectGroupMembersByProjectId(projectId);

        IEnumerable<PersonInfo> personInfos = personService.GetPersons(members.Select(a => a.PersonId).Distinct());

 
        if (personInfos.Count() > 0)
        {
            IEnumerable<CheckinDevice> devices = checkinDeviceService.GetProjectCheckinDevicesByProjectId(projectId);
            foreach (var device in devices)
            {
                CheckinDeviceCommand log = new CheckinDeviceCommand()
                {
                    Name = command.Name,//  考勤机命令.人员离场后下发.GetDescription(),
                    Code = command.Code,// 考勤机命令.人员离场后下发,
                    MessageId = Guid.NewGuid().ToString(),
                    DeviceCode = device.Code,
                    Status = 命令下发状态.待下发,
                    IsAuto = true
                };
                Send(log, device, personInfos);

            }
        }
    }

    /// <summary>
    /// 下发人员信息到设备
    /// </summary>
    /// <param name="command"></param>
    /// <param name="device"></param>
    /// <param name="personInfos"></param>
    /// <returns></returns>
    public void Send(CheckinDeviceCommand command, CheckinDevice device, IEnumerable<PersonInfo> personInfos = null)
    {
        command.MessageId = command.MessageId.Replace("-", "");
        List<AddPersonJobs> jobs = new();
        command.CreateTime = DateTime.Now;
        command.TryCount = 0;
        switch (command.Code)
        {
            case 考勤机命令.批量同步人员:
                var projectGroupMembers = projectGroupMemberService.GetProjectGroupMembersByProjectId(device.ProjectId);
                personInfos = personService.GetPersons(projectGroupMembers.Select(a => a.PersonId).Distinct());
                var personFaces = personFaceService.GetPersonFacesByIdCards(personInfos.Select(a => a.CardNumber).Distinct().ToList());
                foreach (var item in personInfos)
                {
                    AddPersonJobs job = new AddPersonJobs();
                    mapper.Map(item, job);
                    job.StartDate = device.StartDate;
                    job.EndDate = device.EndDate;
                    job.NationCode = (民族)Enum.Parse(typeof(民族), item.Nation);
                    var personFace = personFaces.Where(a => a.IdCard == item.CardNumber).FirstOrDefault();
                    if (personFace != null)
                        job.FacePicURI = $"/api/v1/common/OpenImage/{personFace.Id}";
                    jobs.Add(job);
                }
                command.Jobs = JsonConvert.SerializeObject(jobs);
                projectCheckinDeviceCommandRepository.Insert(command);
                break;

            case 考勤机命令.重启设备:
            case 考勤机命令.设置系统时间:
            case 考勤机命令.清空人员信息:
                projectCheckinDeviceCommandRepository.Insert(command);
                break;

            case 考勤机命令.人员进场后下发:
                if (personInfos == null)
                {
                    IEnumerable<ProjectGroupMember> members = projectGroupMemberService.GetProjectGroupMembersByProjectId(device.ProjectId).Where(a => a.CorpId == device.CorpId && a.Status == 进出场状态.进场);
                    personInfos = personService.GetPersonsByPersonIds(members.Select(a => a.PersonId).Distinct());
                }
                var faces = personFaceService.GetPersonFacesByIdCards(personInfos.Select(a => a.CardNumber).Distinct().ToList());
                foreach (var item in personInfos)
                {
                    AddPersonJobs job = new AddPersonJobs();
                    mapper.Map(item, job);
                    job.StartDate = device.StartDate;
                    job.EndDate = device.EndDate;
                    job.NationCode = (民族)Enum.Parse(typeof(民族), item.Nation);
                    var personFace = faces.Where(a => a.IdCard == item.CardNumber).FirstOrDefault();
                    if (personFace != null)
                        job.FacePicURI = $"/api/v1/common/OpenImage/{personFace.Id}";
                    jobs.Add(job);
                }
                command.Jobs = JsonConvert.SerializeObject(jobs);
                projectCheckinDeviceCommandRepository.Insert(command);
                break;

            case 考勤机命令.人员离场后下发:
                if (personInfos == null)
                {
                    IEnumerable<ProjectGroupMember> members = projectGroupMemberService.GetProjectGroupMembersByProjectId(device.ProjectId).Where(a => a.CorpId == device.CorpId && a.Status == 进出场状态.离场);
                    personInfos = personService.GetPersonsByPersonIds(members.Select(a => a.PersonId).Distinct());
                }
                DeletePersonJobs deletePersonJobs = new DeletePersonJobs();
                deletePersonJobs.CardNumbers = personInfos.Select(a => a.CardNumber).ToArray();
                command.Jobs = JsonConvert.SerializeObject(deletePersonJobs);
                projectCheckinDeviceCommandRepository.Insert(command);
                break;

            default:
                break;
        }
    }
}